import * as React from 'react';
import { Graph, GlobalG6 } from 'viser-graph-react';

const Util = GlobalG6.Util;
const data = {
  nodes: [{
    id: 'node1',
    x: 100,
    y: 100,
    shape: 'circle-animate',
    size: 20,
    label: '图形动画',
    labelCfg: {
      position: 'top'
    }
  }, {
    id: 'node2',
    x: 300,
    y: 200,
    shape: 'background-animate',
    color: '#40a9ff',
    size: 20,
    label: '背景动画',
    labelCfg: {
      position: 'left',
      offset: 10
    }
  }, {
    id: 'node3',
    x: 400,
    y: 100,
    size: [ 40, 40 ],
    shape: 'inner-animate',
    img: '',
    label: '图片动画',
    labelCfg: {
      position: 'right'
    }
  }, {
    id: 'node4',
    x: 300,
    y: 300,
    shape: 'rect',
    label: '无动画',
    labelCfg: {
      position: 'bottom'
    }
  }],
  edges: [{
    source: 'node1',
    target: 'node2'
  },
  {
    source: 'node3',
    target: 'node2'
  },
  {
    source: 'node2',
    target: 'node4'
  }
  ]
};

// 缩放动画
GlobalG6.registerNode('circle-animate', {
  afterDraw(cfg, group) {
    const shape = group.get('children')[0];
    shape.animate({
      repeat: true,
      onFrame(ratio) {
        const diff = ratio <= 0.5 ? ratio * 10 : (1 - ratio) * 10;
        return {
          r: cfg.size / 2 + diff
        };
      }
    }, 3000, 'easeCubic');
  }
}, 'circle');

// 背景动画
GlobalG6.registerNode('background-animate', {
  afterDraw(cfg, group) {
    const r = cfg.size / 2;
    const back1 = group.addShape('circle', {
      zIndex: -3,
      attrs: {
        x: 0,
        y: 0,
        r,
        fill: cfg.color,
        opacity: 0.6
      }
    });
    const back2 = group.addShape('circle', {
      zIndex: -2,
      attrs: {
        x: 0,
        y: 0,
        r,
        fill: cfg.color,
        opacity: 0.6
      }
    });
    const back3 = group.addShape('circle', {
      zIndex: -1,
      attrs: {
        x: 0,
        y: 0,
        r,
        fill: cfg.color,
        opacity: 0.6
      }
    });
    group.sort(); // 排序，根据 zIndex 排序
    back1.animate({ // 逐渐放大，并消失
      r: r + 10,
      opacity: 0.1,
      repeat: true // 循环
    }, 3000, 'easeCubic', null, 0); // 无延迟
    back2.animate({ // 逐渐放大，并消失
      r: r + 10,
      opacity: 0.1,
      repeat: true // 循环
    }, 3000, 'easeCubic', null, 1000); // 1 秒延迟
    back3.animate({ // 逐渐放大，并消失
      r: r + 10,
      opacity: 0.1,
      repeat: true // 循环
    }, 3000, 'easeCubic', null, 2000); // 2 秒延迟
  }
}, 'circle');

// 图片动画
GlobalG6.registerNode('inner-animate', {
  afterDraw(cfg, group) {
    const size = cfg.size;
    const width = size[0] - 12;
    const height = size[1] - 12;
    const image = group.addShape('image', {
      attrs: {
        x: -width / 2,
        y: -height / 2,
        width,
        height,
        img: cfg.img
      }
    });
    image.animate({
      onFrame(ratio) {
        const matrix = Util.mat3.create();
        const toMatrix = Util.transform(matrix, [
          [ 'r', ratio * Math.PI * 2 ]
        ]);
        return {
          matrix: toMatrix
        };
      },
      repeat: true
    }, 3000, 'easeCubic');
  }
}, 'rect');

const graph = {
  data,
  type: 'graph',
  container: 'mount',
  width: 500,
  height: 500,
  pixelRatio: 2,
  renderer: 'svg',
  fitView: true,
  defaultNode: {
    style: {
      fill: '#DEE9FF',
      stroke: '#5B8FF9'
    }
  },
  defaultEdge: {
    style: {
      lineWidth: 1,
      stroke: '#b5b5b5'
    }
  }
};

export default class App extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <div>
        <Graph {...graph}/>
      </div>
    );
  }
}
